﻿using Markdig;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using Sage.MarkdownRenderer.Html;
using System.Diagnostics;

namespace Sage.MarkdownRenderer
{
    /// <summary>
    /// Markdown 渲染内容管理器（基于WebView2封装）
    /// 用于 Markdown 文档的渲染、预览和内容管理
    /// </summary>
    /// <remarks>
    /// <para><strong>主要功能：</strong></para>
    /// <list type="bullet">
    /// <item><description>Markdown 文档渲染和预览</description></item>
    /// <item><description>多种主题模式支持（自动、明亮、暗黑）</description></item>
    /// <item><description>自定义 HTML 内容显示</description></item>
    /// <item><description>安全性配置（禁用开发者工具、右键菜单等）</description></item>
    /// <item><description>外部链接拦截和处理</description></item>
    /// <item><description>内容状态管理和刷新机制</description></item>
    /// </list>
    /// 
    /// <para><strong>使用示例：</strong></para>
    /// <code>
    /// var options = new MarkdownViewManagerOptions { Theme = ThemeMode.Auto };
    /// var manager = new MarkdownViewManager(webView2Control, options);
    /// await manager.InitializeAsync(@"C:\WebViewUserData");
    /// await manager.ShowMarkdownAsync("# Hello World\n这是一个示例");
    /// </code>
    /// </remarks>
    /// <param name="webViewObject">要管理的 WebView2 控件实例，不能为 null</param>
    /// <param name="options">配置选项，如果为 null 则使用默认配置</param>
    /// <exception cref="ArgumentNullException">当 webViewObject 或 options 为 null 时抛出</exception>
    public class MarkdownViewManager(WebView2 webViewObject, MarkdownViewManagerOptions? options = null) : IDisposable
    {
        #region 私有字段

        /// <summary>
        /// WebView2 控件实例
        /// </summary>
        private readonly WebView2 _webView = webViewObject ?? throw new ArgumentNullException(nameof(webViewObject));

        /// <summary>
        /// 配置选项
        /// </summary>
        private readonly MarkdownViewManagerOptions _options = options ?? MarkdownViewManagerOptions.CreateDefault();
        //private readonly MarkdownViewManagerOptions _options = options ?? throw new ArgumentNullException(nameof(options));

        /// <summary>
        /// Markdig 管道配置，支持多种 Markdown 格式解析
        /// </summary>
        /// <remarks>
        /// 配置的扩展功能包括：
        /// <list type="bullet">
        /// <item><description>AdvancedExtensions: 表格、任务列表、删除线等高级扩展</description></item>
        /// <item><description>EmojiAndSmiley: Emoji 表情符号支持</description></item>
        /// <item><description>Mathematics: 数学公式渲染（LaTeX 语法）</description></item>
        /// <item><description>MediaLinks: 媒体链接自动识别</description></item>
        /// <item><description>Figures: 图片标题和描述</description></item>
        /// <item><description>Footers: 脚注功能</description></item>
        /// <item><description>DefinitionLists: 定义列表</description></item>
        /// <item><description>Abbreviations: 缩写词展开</description></item>
        /// <item><description>Citations: 引用和参考文献</description></item>
        /// <item><description>CustomContainers: 自定义容器块</description></item>
        /// <item><description>EmphasisExtras: 增强的强调语法</description></item>
        /// </list>
        /// </remarks>
        private static readonly MarkdownPipeline _markdownPipeline = new MarkdownPipelineBuilder()
            .UseAdvancedExtensions() // 包含表格、任务列表等扩展
            .UseEmojiAndSmiley()     // 支持 Emoji
            .UseMathematics()        // 支持数学公式
            .UseMediaLinks()         // 支持媒体链接
            .UseFigures()           // 支持图片标题
            .UseFooters()           // 支持脚注
            .UseDefinitionLists()   // 支持定义列表
            .UseAbbreviations()     // 支持缩写
            .UseCitations()         // 支持引用
            .UseCustomContainers()  // 支持自定义容器
            .UseEmphasisExtras()    // 支持强调扩展
            .Build();

        /// <summary>
        /// 当前内容状态管理器
        /// 用于保存当前显示的内容信息，支持刷新当前显示和主题切换时的重新渲染
        /// </summary>
        private readonly MarkdownViewContentState _contentState = new();

        /// <summary>
        /// 对象释放状态标记
        /// </summary>
        private bool _disposed = false;
        /// <summary>
        /// 当前主题模式
        /// </summary>
        private ThemeMode _currentTheme = (options ?? MarkdownViewManagerOptions.CreateDefault()).Theme;
        #endregion

        #region 公共属性

        /// <summary>
        /// 获取当前内容状态（只读）
        /// </summary>
        /// <value>当前的内容状态对象，包含内容类型、文本内容等信息</value>
        public MarkdownViewContentState CurrentContentState => _contentState;

        /// <summary>
        /// 获取当前内容类型
        /// </summary>
        /// <value>
        /// 当前显示的内容类型，可能的值：
        /// <list type="bullet">
        /// <item><description><see cref="ContentType.Empty"/>: 空内容</description></item>
        /// <item><description><see cref="ContentType.Initial"/>: 初始页面</description></item>
        /// <item><description><see cref="ContentType.Markdown"/>: Markdown 文档</description></item>
        /// <item><description><see cref="ContentType.CustomContent"/>: 自定义内容</description></item>
        /// </list>
        /// </value>
        public ContentType CurrentContentType => _contentState.Type;

        /// <summary>
        /// 检查是否有内容
        /// </summary>
        /// <value>如果当前有任何形式的内容显示则为 true，否则为 false</value>
        public bool HasContent => _contentState.HasContent;

        /// <summary>
        /// 获取当前主题模式
        /// </summary>
        /// <value>当前使用的主题模式（自动、明亮、暗黑）</value>
        public ThemeMode CurrentTheme => _currentTheme;

        #endregion

        #region 初始化和配置

        /// <summary>
        /// 初始化 WebView2 控件
        /// </summary>
        /// <param name="userDataFolder">WebView2 用户数据存储文件夹路径，如果目录不存在将自动创建</param>
        /// <returns>表示异步初始化操作的任务</returns>
        /// <remarks>
        /// <para><strong>初始化过程包括：</strong></para>
        /// <list type="number">
        /// <item><description>设置用户数据文件夹并确保目录存在</description></item>
        /// <item><description>初始化 CoreWebView2 运行时</description></item>
        /// <item><description>配置安全性和交互性设置</description></item>
        /// <item><description>注册导航事件处理器</description></item>
        /// <item><description>注册键盘事件处理器</description></item>
        /// <item><description>注入安全脚本</description></item>
        /// </list>
        /// 
        /// <para><strong>注意事项：</strong></para>
        /// <list type="bullet">
        /// <item><description>此方法必须在使用其他功能前调用</description></item>
        /// <item><description>用户数据文件夹将存储浏览器缓存、Cookie 等数据</description></item>
        /// <item><description>初始化完成后不会自动加载任何页面，需要手动调用显示方法</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="ObjectDisposedException">当对象已被释放时抛出</exception>
        /// <exception cref="Exception">当初始化过程中发生错误时抛出，包装了内部异常信息</exception>
        public async Task InitializeAsync(string userDataFolder)
        {
            ThrowIfDisposed(); // 检查对象是否已释放
            try
            {
                // 设置 WebView2 创建属性
                _webView.CreationProperties = new CoreWebView2CreationProperties();

                // 确保用户数据文件夹存在
                if (!Directory.Exists(userDataFolder))
                {
                    Directory.CreateDirectory(userDataFolder);
                }
                _webView.CreationProperties.UserDataFolder = userDataFolder;

                // 确保 CoreWebView2 已初始化
                await _webView.EnsureCoreWebView2Async(null);

                // 配置 WebView2 设置
                await ConfigureWebViewAsync();

                // 根据配置注册导航事件处理器（用于拦截外部链接）
                if (_options.UseExternalBrowserForLinks)
                {
                    _webView.CoreWebView2.NavigationStarting += OnNavigationStarting;
                }

                // 根据配置注册键盘事件处理器（用于禁用某些快捷键）
                if (_options.InterceptUIKeyboard)
                {
                    _webView.KeyDown += OnWebViewKeyDown;
                }
                // 根据配置注入安全和功能禁用脚本
                if (_options.InjectSecurityScripts)
                {
                    await InjectDisableScriptsAsync();
                }

                // 这里不自动加载初始页面，交给调用方控制
                if (_options.AutoLoadWelcomePage)
                {
                    await LoadInitialPageAsync();
                }

            }
            catch (Exception ex)
            {
                throw new Exception($"初始化失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 配置 WebView2 的安全性、交互性和用户体验相关设置
        /// </summary>
        /// <returns>表示异步配置操作的任务</returns>
        /// <remarks>
        /// <para><strong>配置项说明：</strong></para>
        /// <list type="bullet">
        /// <item><description><strong>AreDefaultContextMenusEnabled = false</strong>: 禁用右键上下文菜单，防止用户访问"查看源代码"、"检查元素"等功能</description></item>
        /// <item><description><strong>AreDevToolsEnabled = false</strong>: 禁用开发者工具，防止用户通过 F12 等方式打开调试界面</description></item>
        /// <item><description><strong>AreDefaultScriptDialogsEnabled = false</strong>: 禁用 JavaScript 弹窗（alert、confirm、prompt），提供更平滑的用户体验</description></item>
        /// <item><description><strong>IsZoomControlEnabled = false</strong>: 禁用页面缩放功能，保持布局一致性</description></item>
        /// </list>
        /// 
        /// <para><strong>适用场景：</strong></para>
        /// <list type="bullet">
        /// <item><description>文档预览应用：需要防止用户修改或查看页面源码</description></item>
        /// <item><description>内容展示应用：需要保持页面布局的一致性</description></item>
        /// <item><description>嵌入式浏览器：需要限制用户的某些操作权限</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="Exception">当配置过程中发生错误时抛出，包装了内部异常信息</exception>
        private async Task ConfigureWebViewAsync()
        {
            try
            {
                // 确保 CoreWebView2 已完全初始化
                await _webView.EnsureCoreWebView2Async();

                // 获取设置对象
                var settings = _webView.CoreWebView2.Settings;

                // 根据配置设置各项功能
                settings.AreDefaultContextMenusEnabled = !_options.DisableDefaultContextMenu;//禁用默认右键上下文菜单
                settings.AreDevToolsEnabled = !_options.DisableDevTools; //禁用开发者工具
                settings.AreDefaultScriptDialogsEnabled = !_options.DisableScriptDialogs; //禁用默认脚本对话框
                settings.IsZoomControlEnabled = !_options.DisableZoomControl; //禁用缩放控制
            }
            catch (Exception ex)
            {
                throw new Exception($"设置失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 注入禁用脚本到页面
        /// </summary>
        /// <returns>表示异步脚本注入操作的任务</returns>
        /// <remarks>
        /// <para><strong>功能说明：</strong></para>
        /// <list type="bullet">
        /// <item><description>通过 <see cref="HtmlScriptProvider.GetDisableScript()"/> 获取预定义的禁用脚本</description></item>
        /// <item><description>使用 <see cref="CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync"/> 确保脚本在每个页面创建时自动执行</description></item>
        /// <item><description>禁用的功能可能包括：F12 快捷键、右键菜单、文本选择、拖拽等</description></item>
        /// </list>
        /// 
        /// <para><strong>错误处理：</strong></para>
        /// 如果脚本注入失败，会在调试输出和控制台中记录错误信息，然后重新抛出异常。
        /// </remarks>
        /// <exception cref="Exception">当脚本注入失败时抛出，包装了内部异常信息</exception>
        private async Task InjectDisableScriptsAsync()
        {
            try
            {
                var script = HtmlScriptProvider.GetDisableScript();
                await _webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(script);
            }
            catch (Exception ex)
            {
                Debug.Print($"脚本注入失败: {ex.Message}");
                Console.WriteLine($"脚本注入失败: {ex.Message}");
                throw new Exception($"安全脚本注入失败: {ex.Message}", ex);
            }
        }

        #endregion

        #region 事件处理

        /// <summary>
        /// WebView2 键盘事件处理器
        /// </summary>
        /// <param name="sender">事件发送者</param>
        /// <param name="e">键盘事件参数</param>
        /// <remarks>
        /// <para><strong>功能说明：</strong></para>
        /// <list type="bullet">
        /// <item><description>拦截并禁用所有键盘输入事件</description></item>
        /// <item><description>防止用户通过快捷键访问浏览器功能（如 F12 开发者工具）</description></item>
        /// <item><description>在调试模式下输出被禁用的按键信息</description></item>
        /// </list>
        /// 
        /// <para><strong>处理方式：</strong></para>
        /// <list type="bullet">
        /// <item><description><c>e.Handled = true</c>: 标记事件已处理，阻止进一步处理</description></item>
        /// <item><description><c>e.SuppressKeyPress = true</c>: 阻止按键事件继续传播到其他控件</description></item>
        /// </list>
        /// </remarks>
        private void OnWebViewKeyDown(object? sender, KeyEventArgs e)
        {
            // 禁用全部按键输入
            e.Handled = true; // 阻止其他处理
            e.SuppressKeyPress = true; // 阻止按键事件继续传播
            Debug.Print($"按键被禁用: {e.KeyCode}");
        }

        /// <summary>
        /// 处理导航开始事件，拦截外部链接并在默认浏览器中打开
        /// </summary>
        /// <param name="sender">事件发送者</param>
        /// <param name="e">导航事件参数</param>
        /// <remarks>
        /// <para><strong>功能说明：</strong></para>
        /// <list type="bullet">
        /// <item><description>检测用户点击的链接是否为 http 或 https 协议</description></item>
        /// <item><description>如果是外部链接，取消在 WebView2 中的导航</description></item>
        /// <item><description>使用系统默认浏览器打开外部链接</description></item>
        /// </list>
        /// 
        /// <para><strong>安全考虑：</strong></para>
        /// <list type="bullet">
        /// <item><description>防止恶意链接在应用内打开</description></item>
        /// <item><description>保持应用的内容独立性</description></item>
        /// <item><description>提供更好的用户体验</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="InvalidOperationException">当无法打开外部链接时抛出</exception>
        private void OnNavigationStarting(object? sender, CoreWebView2NavigationStartingEventArgs e)
        {
            if (Uri.TryCreate(e.Uri, UriKind.Absolute, out Uri? uri))
            {
                if (uri.Scheme == "http" || uri.Scheme == "https")
                {
                    // 取消在 WebView2 中的导航
                    e.Cancel = true;
                    try
                    {
                        // 在系统默认浏览器中打开链接
                        Process.Start(new ProcessStartInfo
                        {
                            FileName = e.Uri,
                            UseShellExecute = true
                        });
                    }
                    catch (Exception)
                    {
                        throw new InvalidOperationException($"无法打开链接: {e.Uri}");
                    }
                }
            }
        }

        #endregion

        #region 主题和内容管理

        /// <summary>
        /// 设置主题模式并立即应用到当前内容
        /// </summary>
        /// <param name="theme">要设置的主题模式</param>
        /// <returns>表示异步主题设置操作的任务</returns>
        /// <remarks>
        /// <para><strong>功能说明：</strong></para>
        /// <list type="bullet">
        /// <item><description>更新内部主题设置</description></item>
        /// <item><description>刷新当前显示的内容以应用新主题</description></item>
        /// <item><description>如果当前没有内容，则不会有视觉变化</description></item>
        /// </list>
        /// 
        /// <para><strong>支持的主题：</strong></para>
        /// <list type="bullet">
        /// <item><description><see cref="ThemeMode.Auto"/>: 自动模式（跟随系统）</description></item>
        /// <item><description><see cref="ThemeMode.Light"/>: 明亮模式</description></item>
        /// <item><description><see cref="ThemeMode.Dark"/>: 暗黑模式</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="ObjectDisposedException">当对象已被释放时抛出</exception>
        public async Task SetThemeAsync(ThemeMode theme)
        {
            ThrowIfDisposed();
            _currentTheme = theme;
            // 只有在有内容时才刷新，避免无意义的渲染
            if (_contentState.HasContent)
            {
                await RefreshCurrentContentAsync();
            }
        }

        /// <summary>
        /// 刷新当前显示的内容
        /// </summary>
        /// <returns>表示异步刷新操作的任务</returns>
        /// <remarks>
        /// <para><strong>功能说明：</strong></para>
        /// <list type="bullet">
        /// <item><description>根据当前内容状态重新渲染页面</description></item>
        /// <item><description>应用最新的主题设置</description></item>
        /// <item><description>保持内容不变，仅更新样式和配置</description></item>
        /// </list>
        /// 
        /// <para><strong>适用场景：</strong></para>
        /// <list type="bullet">
        /// <item><description>主题切换后需要重新渲染</description></item>
        /// <item><description>配置更改后需要更新显示</description></item>
        /// <item><description>手动刷新当前页面内容</description></item>
        /// </list>
        /// </remarks>
        public Task RefreshCurrentContentAsync()
        {
            if (!_contentState.HasContent)
            {
                // 只有在启用自动加载欢迎页面时才渲染初始页面
                return _options.AutoLoadWelcomePage ? RenderInitialPageAsync() : Task.CompletedTask;
            }

            return _contentState.Type switch
            {
                ContentType.Markdown => RenderMarkdownContentAsync(_contentState.MarkdownText!),
                ContentType.CustomContent => RenderCustomContentAsync(_contentState.CustomTitle!, _contentState.CustomContent!),
                ContentType.Empty => RenderEmptyContentAsync(_contentState.EmptyMessage),
                _ => _options.AutoLoadWelcomePage ? RenderInitialPageAsync(_contentState.InitialTitle, _contentState.InitialContent) : Task.CompletedTask,
            };
        }

        #endregion

        #region 内容显示方法

        /// <summary>
        /// 显示 Markdown 内容
        /// </summary>
        /// <param name="markdownText">要显示的 Markdown 文本内容</param>
        /// <returns>表示异步显示操作的任务</returns>
        /// <remarks>
        /// <para><strong>功能特性：</strong></para>
        /// <list type="bullet">
        /// <item><description>支持标准 Markdown 语法和扩展语法</description></item>
        /// <item><description>自动应用当前主题样式</description></item>
        /// <item><description>启用代码高亮和复制功能</description></item>
        /// <item><description>支持数学公式、表格、任务列表等</description></item>
        /// <item><description>响应式布局适配不同屏幕尺寸</description></item>
        /// </list>
        /// 
        /// <para><strong>内容处理：</strong></para>
        /// <list type="bullet">
        /// <item><description>如果内容为空或只包含空白字符，将显示空内容提示</description></item>
        /// <item><description>使用预配置的 Markdig 管道进行解析</description></item>
        /// <item><description>自动添加 CSS 样式优化显示效果</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="ObjectDisposedException">当对象已被释放时抛出</exception>
        public Task ShowMarkdownAsync(string markdownText)
        {
            ThrowIfDisposed();

            // 更新内容状态
            _contentState.SetMarkdown(markdownText);

            // 渲染内容
            return RenderMarkdownContentAsync(markdownText);
        }

        /// <summary>
        /// 显示 Markdown 内容（使用自定义配置）
        /// </summary>
        /// <param name="markdownText">要显示的 Markdown 文本内容</param>
        /// <param name="htmlTemplateConfig">自定义 HTML 模板配置</param>
        /// <returns>表示异步显示操作的任务</returns>
        /// <remarks>
        /// <para><strong>配置优先级：</strong></para>
        /// <list type="bullet">
        /// <item><description>markdownText 参数优先于配置中的 Content 属性</description></item>
        /// <item><description>如果 markdownText 不为空，将覆盖配置中的 Content</description></item>
        /// <item><description>其他配置项（主题、样式、功能开关等）将按照传入的配置应用</description></item>
        /// </list>
        /// 
        /// <para><strong>自定义配置示例：</strong></para>
        /// <code>
        /// var config = new HtmlTemplateConfig
        /// {
        ///     Theme = ThemeMode.Dark,
        ///     EnableCodeCopy = true,
        ///     MaxWidth = 1000,
        ///     CustomCss = "body { font-size: 16px; }"
        /// };
        /// await manager.ShowMarkdownAsync(markdownText, config);
        /// </code>
        /// </remarks>
        /// <exception cref="ObjectDisposedException">当对象已被释放时抛出</exception>
        public Task ShowMarkdownAsync(string markdownText, HtmlTemplateConfig htmlTemplateConfig)
        {
            ThrowIfDisposed();

            // 更新内容状态
            _contentState.SetMarkdown(markdownText);

            // 使用自定义配置渲染内容
            return RenderMarkdownContentAsync(htmlTemplateConfig, markdownText);
        }

        /// <summary>
        /// 显示自定义内容
        /// </summary>
        /// <param name="title">页面标题</param>
        /// <param name="content">页面内容（HTML 格式）</param>
        /// <returns>表示异步显示操作的任务</returns>
        /// <remarks>
        /// <para><strong>功能说明：</strong></para>
        /// <list type="bullet">
        /// <item><description>显示自定义的 HTML 内容</description></item>
        /// <item><description>使用欢迎页面布局样式</description></item>
        /// <item><description>支持动画效果</description></item>
        /// <item><description>自动应用当前主题</description></item>
        /// </list>
        /// 
        /// <para><strong>适用场景：</strong></para>
        /// <list type="bullet">
        /// <item><description>显示应用介绍或帮助信息</description></item>
        /// <item><description>展示格式化的通知或消息</description></item>
        /// <item><description>显示自定义的 HTML 页面内容</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="ObjectDisposedException">当对象已被释放时抛出</exception>
        public Task ShowCustomContentAsync(string title, string content)
        {
            ThrowIfDisposed();

            // 更新内容状态
            _contentState.SetCustomContent(title, content);

            // 渲染内容
            return RenderCustomContentAsync(title, content);
        }

        /// <summary>
        /// 显示自定义内容（使用自定义配置）
        /// </summary>
        /// <param name="htmlTemplateConfig">完整的 HTML 模板配置</param>
        /// <returns>表示异步显示操作的任务</returns>
        /// <remarks>
        /// <para><strong>配置要求：</strong></para>
        /// <list type="bullet">
        /// <item><description>Title 属性不能为空</description></item>
        /// <item><description>Content 属性不能为空</description></item>
        /// <item><description>其他配置项为可选，将使用默认值</description></item>
        /// </list>
        /// 
        /// <para><strong>高级配置选项：</strong></para>
        /// <list type="bullet">
        /// <item><description>自定义 CSS 样式</description></item>
        /// <item><description>颜色主题配置</description></item>
        /// <item><description>页面最大宽度设置</description></item>
        /// <item><description>动画效果开关</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="ObjectDisposedException">当对象已被释放时抛出</exception>
        public Task ShowCustomContentAsync(HtmlTemplateConfig htmlTemplateConfig)
        {
            ThrowIfDisposed();

            // 更新内容状态
            _contentState.SetCustomContent(htmlTemplateConfig.Title, htmlTemplateConfig.Content);

            // 使用自定义配置渲染内容
            return RenderCustomContentAsync(htmlTemplateConfig);
        }

        /// <summary>
        /// 显示空内容提示
        /// </summary>
        /// <param name="message">要显示的提示消息，如果为空则使用默认消息</param>
        /// <returns>表示异步显示操作的任务</returns>
        /// <remarks>
        /// <para><strong>消息优先级：</strong></para>
        /// <list type="number">
        /// <item><description>使用传入的 message 参数</description></item>
        /// <item><description>如果 message 为空，使用 DefaultEmptyText 属性值</description></item>
        /// <item><description>如果 DefaultEmptyText 也为空，使用硬编码默认值 "暂无内容显示"</description></item>
        /// </list>
        /// 
        /// <para><strong>适用场景：</strong></para>
        /// <list type="bullet">
        /// <item><description>没有可显示的内容时</description></item>
        /// <item><description>数据加载失败时的占位显示</description></item>
        /// <item><description>用户清空内容后的提示</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="ObjectDisposedException">当对象已被释放时抛出</exception>
        public Task ShowEmptyContentAsync(string? message = default)
        {
            ThrowIfDisposed();

            // 更新内容状态
            _contentState.SetEmpty(message);

            // 渲染空内容
            return RenderEmptyContentAsync(message);
        }

        /// <summary>
        /// 显示空内容提示（使用自定义配置）
        /// </summary>
        /// <param name="htmlTemplateConfig">HTML 模板配置</param>
        /// <returns>表示异步显示操作的任务</returns>
        /// <remarks>
        /// <para><strong>配置处理：</strong></para>
        /// <list type="bullet">
        /// <item><description>如果配置中的 Content 为空，将使用默认空内容消息</description></item>
        /// <item><description>可以通过配置自定义空内容页面的样式和布局</description></item>
        /// <item><description>支持自定义 CSS 样式来美化空内容显示</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="ObjectDisposedException">当对象已被释放时抛出</exception>
        public Task ShowEmptyContentAsync(HtmlTemplateConfig htmlTemplateConfig)
        {
            ThrowIfDisposed();

            // 更新内容状态
            _contentState.SetEmpty(htmlTemplateConfig.Content);

            // 使用自定义配置渲染空内容
            return RenderEmptyContentAsync(htmlTemplateConfig);
        }

        /// <summary>
        /// 加载并显示初始页面
        /// </summary>
        /// <param name="title">页面标题，如果为空则使用默认标题</param>
        /// <param name="content">页面内容，如果为空则使用默认内容</param>
        /// <returns>表示异步加载操作的任务</returns>
        /// <remarks>
        /// <para><strong>默认值：</strong></para>
        /// <list type="bullet">
        /// <item><description>默认标题: "Markdown 预览器"</description></item>
        /// <item><description>默认内容: "&lt;p&gt;点击预览按钮开始使用&lt;/p&gt;"</description></item>
        /// </list>
        /// 
        /// <para><strong>页面特性：</strong></para>
        /// <list type="bullet">
        /// <item><description>使用欢迎页面布局</description></item>
        /// <item><description>启用页面动画效果</description></item>
        /// <item><description>应用当前主题样式</description></item>
        /// </list>
        /// </remarks>
        public Task LoadInitialPageAsync(string? title = default, string? content = default)
        {
            // 更新内容状态
            _contentState.SetInitial(title, content);

            // 渲染初始页面
            return RenderInitialPageAsync(title, content);
        }

        /// <summary>
        /// 加载并显示初始页面（使用自定义配置）
        /// </summary>
        /// <param name="htmlTemplateConfig">HTML 模板配置</param>
        /// <returns>表示异步加载操作的任务</returns>
        /// <remarks>
        /// <para><strong>配置默认值处理：</strong></para>
        /// <list type="bullet">
        /// <item><description>如果 Title 为空，将设置为 "Markdown 预览器"</description></item>
        /// <item><description>如果 Content 为空，将设置为默认的欢迎消息</description></item>
        /// </list>
        /// </remarks>
        public Task LoadInitialPageAsync(HtmlTemplateConfig htmlTemplateConfig)
        {
            // 更新内容状态
            _contentState.SetInitial(htmlTemplateConfig.Title, htmlTemplateConfig.Content);

            // 使用自定义配置渲染初始页面
            return RenderInitialPageAsync(htmlTemplateConfig);
        }

        #endregion

        #region 渲染方法（纯渲染，不更新状态）

        /// <summary>
        /// 渲染 Markdown 内容为 HTML 并显示
        /// </summary>
        /// <param name="markdownText">要渲染的 Markdown 文本</param>
        /// <returns>表示异步渲染操作的任务</returns>
        /// <remarks>
        /// <para><strong>渲染流程：</strong></para>
        /// <list type="number">
        /// <item><description>检查内容是否为空，为空则显示空内容提示</description></item>
        /// <item><description>使用 Markdig 管道将 Markdown 转换为 HTML</description></item>
        /// <item><description>应用预定义的 HTML 模板和样式</description></item>
        /// <item><description>注入自定义 CSS 优化显示效果</description></item>
        /// <item><description>在 WebView2 中显示最终的 HTML</description></item>
        /// </list>
        /// 
        /// <para><strong>样式特性：</strong></para>
        /// <list type="bullet">
        /// <item><description>减少页面顶部空白间距</description></item>
        /// <item><description>优化标题元素的边距</description></item>
        /// <item><description>启用代码复制功能</description></item>
        /// <item><description>支持响应式布局</description></item>
        /// <item><description>使用紫色主题配色方案</description></item>
        /// </list>
        /// </remarks>
        private Task RenderMarkdownContentAsync(string markdownText)
        {
            // 空内容检查
            if (string.IsNullOrWhiteSpace(markdownText))
            {
                return RenderEmptyContentAsync(_options.DefaultEmptyText ?? "请输入 Markdown 内容...");
            }

            // 将 Markdown 转换为 HTML
            var markdownHtml = Markdig.Markdown.ToHtml(markdownText, _markdownPipeline);

            // 配置 HTML 模板
            var config = new HtmlTemplateConfig
            {
                Content = markdownHtml,
                ShowWelcomeLayout = false, // 不使用欢迎页面布局
                Theme = _currentTheme, // 如果没有使用配置对象则使用自动主题
                EnableAnimation = true,
                EnableCodeCopy = true,
                EnableResponsive = true,
                EnablePrintStyles = true,
                EnableHoverAnimations = false,
                MaxWidth = 1200,
                // 自定义 CSS 优化显示效果
                CustomCss = @"
                /* 减少页面顶部间距 */
                body {
                    padding-top: 10px !important;
                }
                
                /* 移除第一个元素的顶部边距 */
                body > h1:first-child,
                body > h2:first-child,
                body > h3:first-child,
                body > h4:first-child,
                body > h5:first-child,
                body > h6:first-child,
                body > p:first-child {
                    margin-top: 0 !important;
                }
                
                /* 减少标题的默认边距 */
                h1, h2, h3, h4, h5, h6 {
                    margin-top: 1em !important;
                }
                
                h1:first-child, h2:first-child, h3:first-child {
                    margin-top: 0 !important;
                }"
            };

            // 生成并显示 HTML
            var html = HtmlTemplateBuilder.CreateTemplate(config);
            _webView.NavigateToString(html);
            return Task.CompletedTask;
        }

        /// <summary>
        /// 渲染 Markdown 内容为 HTML 并显示（使用自定义配置）
        /// </summary>
        /// <param name="htmlTemplateConfig">HTML 模板配置</param>
        /// <param name="markdownText">要渲染的 Markdown 文本</param>
        /// <returns>表示异步渲染操作的任务</returns>
        /// <remarks>
        /// <para><strong>内容优先级：</strong></para>
        /// <list type="bullet">
        /// <item><description>如果 markdownText 不为空，将覆盖配置中的 Content 属性</description></item>
        /// <item><description>如果两者都为空，将显示空内容提示</description></item>
        /// </list>
        /// </remarks>
        private Task RenderMarkdownContentAsync(HtmlTemplateConfig htmlTemplateConfig, string markdownText)
        {
            ArgumentNullException.ThrowIfNull(htmlTemplateConfig);

            // 内容检查
            if (string.IsNullOrWhiteSpace(htmlTemplateConfig.Content) && string.IsNullOrWhiteSpace(markdownText))
            {
                return RenderEmptyContentAsync(_options.DefaultEmptyText ?? "请输入 Markdown 内容...");
            }

            // 如果提供了 Markdown 文本，优先使用它
            if (!string.IsNullOrWhiteSpace(markdownText))
            {
                var markdownHtml = Markdown.ToHtml(markdownText, _markdownPipeline);
                htmlTemplateConfig.Content = markdownHtml;
            }

            // 生成并显示 HTML
            var html = HtmlTemplateBuilder.CreateTemplate(htmlTemplateConfig);
            _webView.NavigateToString(html);
            return Task.CompletedTask;
        }

        /// <summary>
        /// 渲染自定义内容并显示
        /// </summary>
        /// <param name="title">页面标题</param>
        /// <param name="content">页面内容（HTML 格式）</param>
        /// <returns>表示异步渲染操作的任务</returns>
        /// <exception cref="ArgumentException">当 title 或 content 为空时抛出</exception>
        private Task RenderCustomContentAsync(string title, string content)
        {
            ArgumentException.ThrowIfNullOrWhiteSpace(title);
            ArgumentException.ThrowIfNullOrWhiteSpace(content);

            var config = new HtmlTemplateConfig
            {
                Title = title,
                Content = content,
                ShowWelcomeLayout = true,
                Theme = _currentTheme,
                EnableAnimation = true
            };

            var html = HtmlTemplateBuilder.CreateTemplate(config);
            _webView.NavigateToString(html);
            return Task.CompletedTask;
        }

        /// <summary>
        /// 渲染自定义内容并显示（使用自定义配置）
        /// </summary>
        /// <param name="htmlTemplateConfig">HTML 模板配置</param>
        /// <returns>表示异步渲染操作的任务</returns>
        /// <exception cref="ArgumentNullException">当配置对象为 null 时抛出</exception>
        /// <exception cref="ArgumentException">当配置中的 Title 或 Content 为空时抛出</exception>
        private Task RenderCustomContentAsync(HtmlTemplateConfig htmlTemplateConfig)
        {
            ArgumentNullException.ThrowIfNull(htmlTemplateConfig);
            ArgumentException.ThrowIfNullOrWhiteSpace(htmlTemplateConfig.Title);
            ArgumentException.ThrowIfNullOrWhiteSpace(htmlTemplateConfig.Content);

            var html = HtmlTemplateBuilder.CreateTemplate(htmlTemplateConfig);
            _webView.NavigateToString(html);
            return Task.CompletedTask;
        }

        /// <summary>
        /// 渲染空内容提示并显示
        /// </summary>
        /// <param name="message">要显示的提示消息</param>
        /// <returns>表示异步渲染操作的任务</returns>
        private Task RenderEmptyContentAsync(string? message = default)
        {
            var config = new HtmlTemplateConfig
            {
                Content = $"<div class='empty-content'>{message ?? _options.DefaultEmptyText ?? "暂无内容显示"}</div>",
                ShowWelcomeLayout = true,
                Theme = _currentTheme,
                EnableAnimation = true
            };

            var html = HtmlTemplateBuilder.CreateTemplate(config);
            _webView.NavigateToString(html);
            return Task.CompletedTask;
        }

        /// <summary>
        /// 渲染空内容提示并显示（使用自定义配置）
        /// </summary>
        /// <param name="htmlTemplateConfig">HTML 模板配置</param>
        /// <returns>表示异步渲染操作的任务</returns>
        /// <exception cref="ArgumentNullException">当配置对象为 null 时抛出</exception>
        private Task RenderEmptyContentAsync(HtmlTemplateConfig htmlTemplateConfig)
        {
            ArgumentNullException.ThrowIfNull(htmlTemplateConfig);

            if (string.IsNullOrWhiteSpace(htmlTemplateConfig.Content))
            {
                htmlTemplateConfig.Content = $"<div class='empty-content'>{_options.DefaultEmptyText ?? "暂无内容显示"}</div>";
            }

            var html = HtmlTemplateBuilder.CreateTemplate(htmlTemplateConfig);
            _webView.NavigateToString(html);
            return Task.CompletedTask;
        }

        /// <summary>
        /// 渲染初始页面并显示
        /// </summary>
        /// <param name="title">页面标题</param>
        /// <param name="content">页面内容</param>
        /// <returns>表示异步渲染操作的任务</returns>
        private Task RenderInitialPageAsync(string? title = default, string? content = default)
        {
            var config = new HtmlTemplateConfig
            {
                Title = title ?? "Markdown 预览器",
                Content = content ?? "<p>点击预览按钮开始使用</p>",
                ShowWelcomeLayout = true,
                Theme = _currentTheme,
                EnableAnimation = true,
                EnableHoverAnimations = false,
            };

            var html = HtmlTemplateBuilder.CreateTemplate(config);
            _webView.NavigateToString(html);
            return Task.CompletedTask;
        }

        /// <summary>
        /// 渲染初始页面并显示（使用自定义配置）
        /// </summary>
        /// <param name="htmlTemplateConfig">HTML 模板配置</param>
        /// <returns>表示异步渲染操作的任务</returns>
        /// <exception cref="ArgumentNullException">当配置对象为 null 时抛出</exception>
        private Task RenderInitialPageAsync(HtmlTemplateConfig htmlTemplateConfig)
        {
            ArgumentNullException.ThrowIfNull(htmlTemplateConfig);

            // 设置默认值
            if (string.IsNullOrWhiteSpace(htmlTemplateConfig.Title))
            {
                htmlTemplateConfig.Title = "Markdown 预览器";
            }
            if (string.IsNullOrWhiteSpace(htmlTemplateConfig.Content))
            {
                htmlTemplateConfig.Content = "<p>点击预览按钮开始使用</p>";
            }

            var html = HtmlTemplateBuilder.CreateTemplate(htmlTemplateConfig);
            _webView.NavigateToString(html);
            return Task.CompletedTask;
        }

        #endregion

        #region IDisposable 实现

        /// <summary>
        /// 释放由 WebViewManager 使用的所有资源
        /// </summary>
        /// <remarks>
        /// <para><strong>释放的资源包括：</strong></para>
        /// <list type="bullet">
        /// <item><description>移除 WebView2 事件处理器</description></item>
        /// <item><description>清理内部状态</description></item>
        /// <item><description>防止内存泄漏</description></item>
        /// </list>
        /// 
        /// <para><strong>注意事项：</strong></para>
        /// <list type="bullet">
        /// <item><description>调用后对象将不可再使用</description></item>
        /// <item><description>重复调用是安全的</description></item>
        /// <item><description>建议在不再需要时及时调用</description></item>
        /// </list>
        /// </remarks>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放资源的具体实现
        /// </summary>
        /// <param name="disposing">指示是否正在释放托管资源</param>
        /// <remarks>
        /// <para><strong>释放过程：</strong></para>
        /// <list type="bullet">
        /// <item><description>检查是否已经释放过</description></item>
        /// <item><description>移除导航事件处理器</description></item>
        /// <item><description>移除键盘事件处理器</description></item>
        /// <item><description>记录释放状态</description></item>
        /// <item><description>处理释放过程中的异常</description></item>
        /// </list>
        /// </remarks>
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    try
                    {
                        // 移除事件处理器，防止内存泄漏
                        if (_webView?.CoreWebView2 != null)
                        {
                            // 根据配置移除相应的事件处理器，防止内存泄漏
                            if (_options.UseExternalBrowserForLinks && _webView?.CoreWebView2 != null)
                            {
                                _webView.CoreWebView2.NavigationStarting -= OnNavigationStarting;
                            }
                        }
                        if (_webView != null)
                        {
                            if (_options.InterceptUIKeyboard && _webView != null)
                            {
                                _webView.KeyDown -= OnWebViewKeyDown;
                            }
                        }
                        Debug.WriteLine("WebViewManager 资源已释放");
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine($"释放 WebViewManager 资源时发生错误: {ex.Message}");
                    }
                }
                _disposed = true;
            }
        }

        /// <summary>
        /// 检查对象是否已被释放，如果已释放则抛出异常
        /// </summary>
        /// <exception cref="ObjectDisposedException">当对象已被释放时抛出</exception>
        private void ThrowIfDisposed()
        {
            ObjectDisposedException.ThrowIf(_disposed, this);
        }

        /// <summary>
        /// 析构函数，确保资源被正确释放
        /// </summary>
        /// <remarks>
        /// 如果忘记调用 <see cref="Dispose()"/> 方法，析构函数将确保资源得到释放。
        /// 但建议显式调用 Dispose() 以获得更好的性能。
        /// </remarks>
        ~MarkdownViewManager()
        {
            Dispose(false);
        }

        #endregion
    }
}
